// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameplayEffectTypes.h"

#include "LyraGameplayEffectContext.generated.h"

class AActor;
/**
 * Base class for archives that can be used for loading, saving, and garbage
 * collecting in a byte order neutral way.
 */

/**
 * FArchive: 
 * 存档的基类，支持以字节序无关的方式进行加载、保存和垃圾回收操作。
 */
class FArchive;
class ILyraAbilitySourceInterface;
class UObject;
class UPhysicalMaterial;

USTRUCT()
struct FLyraGameplayEffectContext : public FGameplayEffectContext
{
	GENERATED_BODY()

	FLyraGameplayEffectContext()
		: FGameplayEffectContext()
	{
	}

	FLyraGameplayEffectContext(AActor* InInstigator, AActor* InEffectCauser)
		: FGameplayEffectContext(InInstigator, InEffectCauser)
	{
	}

	/** Returns the wrapped FLyraGameplayEffectContext from the handle, or nullptr if it doesn't exist or is the wrong type */

	/** 从句柄中返回封装的FLyraGameplayEffectContext，如果不存在或者是错误类型则返回nullptr。 */
	static LYRAGAME_API FLyraGameplayEffectContext* ExtractEffectContext(struct FGameplayEffectContextHandle Handle);

	/** Sets the object used as the ability source */

	/** 设置对象用于作为能力来源。 */
	void SetAbilitySource(const ILyraAbilitySourceInterface* InObject, float InSourceLevel);

	/** Returns the ability source interface associated with the source object. Only valid on the authority. */

	/** 返回这个能力来源接口关联的来源对象。仅在权威有效。 */
	const ILyraAbilitySourceInterface* GetAbilitySource() const;

	virtual FGameplayEffectContext* Duplicate() const override
	{
		FLyraGameplayEffectContext* NewContext = new FLyraGameplayEffectContext();
		*NewContext = *this;

		/** Returns hit result, this can be null */

		/** GetHitResult: 返回碰撞结果，能够为空。 */
		if (GetHitResult())
		{
			// Does a deep copy of the hit result

			// 做一个深复制作为碰撞结果。

			/** Add a hit result for targeting */

			/** AddHitResult: 为节点添加一个碰撞结果。 */
			NewContext->AddHitResult(*GetHitResult(), true);
		}
		return NewContext;
	}

	virtual UScriptStruct* GetScriptStruct() const override
	{
		return FLyraGameplayEffectContext::StaticStruct();
	}

	/** Overridden to serialize new fields */

	// 覆盖序列化的新的字段。
	virtual bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess) override;

	/** Returns the physical material from the hit result if there is one */

	/** 对于这个碰撞结果存在命中的物理材质，则返回物理材质。 */
	const UPhysicalMaterial* GetPhysicalMaterial() const;

public:
	/** ID to allow the identification of multiple bullets that were part of the same cartridge */

	/** 用于识别属于同一弹药筒的多发子弹的标识。 */
	UPROPERTY()
	int32 CartridgeID = -1;

protected:
	/** Ability Source object (should implement ILyraAbilitySourceInterface). NOT replicated currently */

	/** 能力来源对象(应该实现ILyraAbilitySourceInterface)。当前不是复制的。 */
	UPROPERTY()
	TWeakObjectPtr<const UObject> AbilitySourceObject;
};

/** type traits to cover the custom aspects of a script struct **/

/** TStructOpsTypeTraitsBase2: 覆盖脚本结构体的自定义方面的类型特征。 */
template<>
struct TStructOpsTypeTraits<FLyraGameplayEffectContext> : public TStructOpsTypeTraitsBase2<FLyraGameplayEffectContext>
{
	enum
	{
		WithNetSerializer = true,
		WithCopy = true
	};
};

